// window.onerror = function(errorMessage, scriptURI, lineNumber, columnNumber, errorObj) {
//      window.alert("错误" + errorMessage + " 脚本" +  scriptURI + " 位置" + lineNumber + ":" + columnNumber
//      + " 对象" + errorObj)
//      return false;
// }

window.__onNativeCall = function(args) {
    if (!window.__native) {
        return;
    }
    window.__native.__onNativeCall(args.name, args.id, args.isRemoveCallback, args.error, args.data);
};

import {Task} from "./task.js";

/**
 * 底层接口，应用层请勿直接调用，以免打乱运行环境
 * @version 2
 * @author GuoHua Liu
 * @copyright Copyright © 2019 GuoHua Liu. All rights reserved.
 */
class Native {

    constructor() {
        this.__observerss = {}; // 事件观察
        this.__waitCallbacks = {};
        this.__id = 1;
        // eslint-disable-next-line no-prototype-builtins
        this.__isQt = window.hasOwnProperty("qt");
    }

    /**
      * 获取该类的单例
      * @returns {Native}
      */
    static getInstance() {
        if(window.__native) {
            return window.__n;
        }
        window.__n = new Native();
        return window.__n;
    }

    isHos() {
        return this.isHos() || this.isAndroid() || this.__isQt;
    }

    isQt() {
        return this.__isQt;
    }

    isIOS() {
        // eslint-disable-next-line no-prototype-builtins
        if (window.hasOwnProperty("webkit")
              && typeof window.webkit.messageHandlers
              && typeof window.webkit.messageHandlers.toast
        ) {
            return true;
        }
        return false;
    }

    isAndroid() {
        return !!window.__HosBridge;
    }

    __addRequest (request) {
        // eslint-disable-next-line no-constant-condition
        while(true) {
            if(this.__id > 65536) {
                this.__id = 1;
            }
            if (this.__waitCallbacks[this.__id += 1]) {
                continue;
            }
            break;
        }

        this.__waitCallbacks[this.__id] = request;
        request.__id = this.__id;
        return request.__id;
    }

    __delRequest (task) {
        // console.log("删除任务:" + task.__id)
        if (this.__waitCallbacks[task.__id]) {
            this.__waitCallbacks[task.__id] = undefined;
            task.__id = 0; //
        }
        // console.warn("尝试删除任务,但是该任务不存-->" + task.__id)
    }


    __onNativeCall(name, id, isRemoveCallback, error, data) {

        // 事件

        if (id < 0) {
            this.__fireEvent(name, id, data);
        }

        // 普通任务

        let task = this.__waitCallbacks[id];

        if (task) {
            // console.log("任务处理结束-->" + task.__id + "," + id)
            if (!error) {
                // console.log("解决任务-->" + task.__id + "," + task.name)
                task.__resolve(data);//
            } else {
                // console.log("失败任务-->" + task.__id + "," + task.name)
                task.__reject(data);
            }

            if (isRemoveCallback) {
                this.__delRequest(task);
            }
        }
    }


    exec(cmd) {
        let path = "cmd/" + cmd;
        let xhr = new XMLHttpRequest();
        xhr.open("get", path, false);
        xhr.send(null);
        return xhr.responseText;
    }


    /**
     *
     * @param name
     * @param data
     * @return {object}
     */
    syncCallNative (name, data) {
        let res = prompt(name, JSON.stringify(data));
        return JSON.parse(res);
    }

    /**
       * 添加观察者
       * @param {String} name 插件名称
       * @param {*} context onevent函数所在的上下文
       * @param {Function} onevent 观察者函数
       */
    addObserver(name, context, onevent) {

        if (typeof onevent != "function") {
            let ctx = onevent;
            onevent = context;
            context = ctx;
        }

        if (typeof onevent != "function") {
            console.error("参数错误");
        }

        let observer = {"onevent": onevent, "context": context};

        let observers = this.__observerss[name];
        if (!observers) {
            observers = this.__observerss[name] = [observer];
        } else {
            this.delObserver(name, onevent); // 避免多次添加
            observers.push(observer);
        }
        // console.log("addObserver-->" + name + "," + observers.length, onevent, observer)
    }

    /**
      * 发射事件
      * @param {String} name
      * @param {Number} id
      * @param {Object} data
      */
    __fireEvent(name, id, data) {
        // console.log("发射事件", name, id, data)
        let observers = this.__observerss[name];
        if (observers) {
            (function () {
                let i = observers.length;
                while(i--){
                    let observer = observers[i];
                    if(!observer || !observer.onevent){
                        // console.log("清理无效观察者", observer, observers.length)
                        observers.splice(i,1);
                    }
                }
            })();

            for (let index in observers) {
                let observer = observers[index];
                // console.log("观察者", observer, "执行函数", observer.onevent, "上下文", observer.context)
                if (observer.context) {
                    // 用户指定了执行上下文
                    observer.onevent.call(observer.context, {"name": name, "id": id, "data": data});
                } else {
                    observer.onevent({"name": name, "id": id, "data": data});
                }
            }
        }
    }

    /**
      * 删除观察者
      * @param {String} name 插件名称
      * @param {*} onevent 观察者函数
      */
    delObserver(name, onevent=null) {
        let observers = this.__observerss[name];
        if (!observers) {
            // console.warn("尝试移除" + name + "的一个观察者,但是它不存在")
            return;
        }
        // >> 删除所有观察者 since 2
        if(!onevent) {
            this.__observerss[name] = [];
            console.log("delObserver-->remove all observer");
            return;
        }
        // <<
        for(let index in observers) {
            // eslint-disable-next-line no-prototype-builtins
            if (observers.hasOwnProperty(index)) {
                const observer = observers[index];
                if(observer.onevent === onevent) {
                    console.log("delObserver-->remove the observer");
                    observer.onevent = undefined;
                    observer.context = undefined;
                    observers.splice(index, 1);
                    break;
                }
            }
        }

        // console.log("delObserver-->" + name + "," + observers.length)
    }

    /**
      * 调用底层异步执行任务
      * @param {String} name 插件名称
      * @param {Object} data  发送的数据
      * @param {boolean} isWaitCallBack 是否要求回调
      * @param {function} onsuccess 成功回调函数
      * @param {function} onfail 失败回调函数
      * @returns {Task}
      */
    callNative (name, data, isWaitCallBack = false, onsuccess = undefined, onfail = undefined) {
        if (isWaitCallBack) {
            let task = new Task();
            task.__user_resolove = onsuccess;
            task.__user_reject = onfail;
            task.name = name;
            let id = this.__addRequest(task);
            // console.log("提交新任务-->" + task.__id + "," + task.name)//

            if (this.isIOS()) {
                window.webkit.messageHandlers.__onJsCall.postMessage(
                    {name: name,
                        id: id,
                        data: data});
            } else if (this.isAndroid()) {
                window.__HosBridge.__onJsCall(JSON.stringify(
                    {name: name,
                        id: id,
                        data: data}));
            }

            task.__setAbort(()=>{
                // console.log("打断任务-->" + task.__id + "," + task.name)//
                if (task.__id != 0) {
                    this.__delRequest(task);
                }
            });
            //  console.log("任务已经完成提交-->" + task.__id + "," + task.name)//
            return task;
        }
        if (this.isIOS()) {
            window.webkit.messageHandlers.__onJsCall.postMessage(
                {name: name,
                    id: 0, // 此时id无用
                    data: data});
            return null;
        } else if (this.isAndroid()) {
            window.__HosBridge.__onJsCall(JSON.stringify(
                {name: name,
                    id: 0, // 此时id无用
                    data: data}));
            return null;
        } else if (this.__isQt) {
            return null;
        }
        // alert("环境不支持" + name)
        return null;
    }
}


export {Native};
